package work;


import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

public class MyDatasource1 implements DataSource 
{
    LinkedList<Connection> list=new LinkedList<>();

    public MyDatasource1() {
        for (int i = 0; i <5; i++) {
            Connection conn=JDBCUtils.getConnection();
            list.addLast(conn);
        }
        System.out.println("连接池初始化成功，大小是"+list.size());
    }
    @Override
    public Connection getConnection() throws SQLException {
        //这里刚好是Connectiond的对象用来后面做动态代理方法的传参
        Connection conn = list.removeLast();
        ClassLoader classLoader = conn.getClass().getClassLoader();
        //本题使用.getInterfaces()获取实现的接口是错误的，必须使用java.sql.Connection.class来获取实现的接口Connection
        //因为是通过其他类间接实现了接口Connection，所以.getInterfaces()是错误的
//        Class<?>[] interfaces = conn.getClass().getInterfaces();
        Class<?>[] interfaces = {java.sql.Connection.class};
        //根据反射相关原理方法，获取动态代理（实现接口 InvocationHandler）
        InvocationHandler h = new InvocationHandler() {
            @Override
            //反射拦截所有方法
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //对代理的Connection接口的close方法进行改写
                String name = method.getName();
                if (name.equals("close")) {
                    list.addFirst(conn);
                    System.out.println("连接返还池中");
                    System.out.println("此时池子 中还有" + list.size() + "个连接");
                }
                else{
                    //其他方法和参数原样返回（回传Connection的对conn和参数）
                    Object invoke = method.invoke(conn, args);
                    return invoke;
                }
                return conn;
            }
        };
        //获得某类的代理，需传入类加载器，所实现的接口对象和动态代理对象本身
        //不管外界获取哪个Connection对象，均进行了动态代理
        Connection proxy= (Connection) Proxy.newProxyInstance(classLoader,interfaces,h);
        return proxy;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}
